package cn.itcast.nems.studentrecord.service.impl.studentrecord;

import cn.hutool.core.lang.Assert;
import cn.itcast.ic.common.exception.v2.BizExceptionProducer;
import cn.itcast.nems.base.api.ClazzApi;
import cn.itcast.nems.base.dto.ClazzDTO;
import cn.itcast.nems.common.enumeration.NemsErrorBodyEnum;
import cn.itcast.nems.journal.service.JournalDropoutService;
import cn.itcast.nems.journal.service.JournalTransferLineService;
import cn.itcast.nems.manager.util.CustomBeanUtil;
import cn.itcast.nems.oldems.api.StudentApi;
import cn.itcast.nems.oldems.dto.StudentBelongerDTO;
import cn.itcast.nems.oldems.dto.StudentClazzInfoDTO;
import cn.itcast.nems.oldems.dto.StudentClazzStatisticsInfoDTO;
import cn.itcast.nems.oldems.dto.StudentInfoDTO;
import cn.itcast.nems.studentrecord.constant.ReferenceTypeEnum;
import cn.itcast.nems.studentrecord.dao.dataobject.StudentRecordDO;
import cn.itcast.nems.studentrecord.dao.entity.JournalDropout;
import cn.itcast.nems.studentrecord.dao.entity.JournalTransferLine;
import cn.itcast.nems.studentrecord.dao.entity.StudentRecord;
import cn.itcast.nems.studentrecord.dao.mapper.StudentRecordMapper;
import cn.itcast.nems.studentrecord.dto.StudentRecordInfoDTO;
import cn.itcast.nems.studentrecord.dto.StudentRecordInfoQueryDTO;
import cn.itcast.nems.studentrecord.dto.StudentRecordRefundInfoDTO;
import cn.itcast.nems.studentrecord.enumeration.StudentRecordStateEnum;
import cn.itcast.nems.studentrecord.service.studentrecord.StudentRecordInfoService;
import cn.itcast.nems.studentrecord.util.StudentRecordInfoServiceUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.*;
import java.util.stream.Collectors;

@Service
@RequiredArgsConstructor
@Slf4j
public class StudentRecordInfoServiceImpl implements StudentRecordInfoService {
    private final JournalDropoutService journalDropoutService ;
    private final StudentRecordMapper studentRecordMapper;
    private final StudentApi studentApi;
    private final JournalTransferLineService journalTransferLineService ;
    private final ClazzApi clazzApi ;

    @Override
    public List<StudentRecordInfoDTO> queryStudentRecordListByClazzId(StudentRecordInfoQueryDTO queryDTO) {
        StudentRecordDO recordDO = CustomBeanUtil.copyProperties(queryDTO, new StudentRecordDO());
        List<StudentRecordDO> recordList = studentRecordMapper.queryStudentRecordListByParams(recordDO);
        if (CollectionUtils.isEmpty(recordList)) {
            return new ArrayList<>();
        }
        return recordList.stream().map(StudentRecordInfoServiceUtil::convertToStudentRecordInfoDTO).toList();
    }

    private ClazzDTO checkCurrentClazzRecord(String studentRecordId) {
        if (!StringUtils.hasText(studentRecordId)) {
            return null;
        }
        StudentRecord studentRecord = studentRecordMapper.selectById(studentRecordId);
        if (!ReferenceTypeEnum.SUSPENSION.name().equals(studentRecord.getSource())) {
            return null;
        }
        //  检查学籍所在的班级是否为 【普通班】
        ClazzDTO clazzDTO   = clazzApi.queryByClassId(studentRecord.getClazzId()) ;
        Assert.notNull(clazzDTO  , BizExceptionProducer.produce(NemsErrorBodyEnum.DATA_EXIST , "班级ID："+  studentRecord.getClazzId() )) ;
        if(!clazzDTO.getSuspensionFlag()) {
            return  null ;
        }
        final String journalLineId = this.journalTransferLineService.findLineIdByJobStudentRecordId(studentRecordId);
        if (StringUtils.hasText(journalLineId)) {
            final JournalTransferLine line = this.journalTransferLineService.getById(journalLineId);
            StudentRecord suspensionOriginStudentRecord = studentRecordMapper.selectById(line.getOriginStudentRecordId());
            cn.hutool.core.lang.Assert.notNull(
                    suspensionOriginStudentRecord,
                    BizExceptionProducer.produce(NemsErrorBodyEnum.DATA_EXIST, "退费休学原学籍ID：" + line.getOriginStudentRecordId())
            );
            log.info("当前学籍ID：{}，班级ID：{},休学原学籍ID：{}, 原学籍对应班级ID：{}",
                    studentRecord.getId(), studentRecord.getClazzId(),
                    line.getOriginStudentRecordId(), suspensionOriginStudentRecord.getClazzId());
            return clazzApi.queryByClassId(suspensionOriginStudentRecord.getClazzId());
        }
        return null;
    }


    @Override
    public List<StudentInfoDTO> queryStudentRecordListByStudentIds(Set<Integer> studentIds, String keyword) {
        List<StudentInfoDTO> list = Objects.requireNonNullElse(studentApi.queryStudentListByIds(studentIds, keyword), new ArrayList<>());
        // 当前所在班级
        StudentRecordDO recordDO = new StudentRecordDO();
        recordDO.setStudentIds(studentIds);
        // recordDO.setIsCurrentClazz(true);
        List<StudentRecordDO> recordList = studentRecordMapper.queryStudentRecordListByParams(recordDO);
        final Map<Integer, List<StudentRecordDO>> currentClazzMap = Objects.requireNonNullElse(recordList, new ArrayList<StudentRecordDO>())
                .stream().collect(Collectors.groupingBy(StudentRecordDO::getStudentId, Collectors.toList()));
        // 学生-院校归属人
        List<StudentBelongerDTO> belongerList = studentApi.queryStudentBelongerByIds(studentIds);
        final Map<Integer, List<StudentBelongerDTO>> belongerMap = Objects.requireNonNullElse(belongerList, new ArrayList<StudentBelongerDTO>())
                .stream().collect(Collectors.groupingBy(StudentBelongerDTO::getStudentId, Collectors.toList()));
        list.forEach(item -> {
            StudentRecordInfoServiceUtil.convertToStudentInfoDTO(item, currentClazzMap, belongerMap);
            ClazzDTO clazzDTO = this.checkCurrentClazzRecord(item.getStudentRecordId());
            if (Objects.nonNull(clazzDTO)) {
                log.info("【根据ID查询学籍列表】当前班级对应休学学籍， 切换至原学籍班级：{}" , JSON.toJSONString(clazzDTO , SerializerFeature.DisableCircularReferenceDetect));
                item.setCurrentClazzId(clazzDTO.getClassId());
                item.setCurrentClazzName(clazzDTO.getClassName());
            }
        });
        return list;
    }

    @Override
    public List<StudentClazzInfoDTO> queryClazzListByStudentNos(Set<String> studentNos) {
        List<StudentClazzInfoDTO> list = studentApi.queryClazzListByStudentNos(studentNos);
        if (CollectionUtils.isEmpty(list)) {
            return null;
        }
        Set<Integer> studentIds = list.stream().map(StudentClazzInfoDTO::getStudentId).collect(Collectors.toSet());
        StudentRecordDO recordDO = new StudentRecordDO();
        recordDO.setStudentIds(studentIds);
        List<StudentRecordDO> recordList = studentRecordMapper.queryStudentRecordListByParams(recordDO);
        final Map<Integer, List<StudentRecordDO>> map = Objects.requireNonNullElse(recordList, new ArrayList<StudentRecordDO>())
                .stream()
                .collect(Collectors.groupingBy(StudentRecordDO::getStudentId, Collectors.toList()));
        list.forEach(item -> {
            StudentRecordInfoServiceUtil.convertToStudentClazzInfoDTO(item, map);
            ClazzDTO clazzDTO = this.checkCurrentClazzRecord(item.getStudentRecordId());
            if (Objects.nonNull(clazzDTO)) {
                log.info("【根据学号查询学籍班级列表】当前班级对应休学学籍， 切换至原学籍班级：{}" , JSON.toJSONString(clazzDTO , SerializerFeature.DisableCircularReferenceDetect));
                item.setCurrentClazzId(clazzDTO.getClassId());
            }
        });
        return list;
    }

    @Override
    public StudentClazzStatisticsInfoDTO statisticsByClassId(Integer clazzId) {
        StudentClazzStatisticsInfoDTO statisticsInfoDTO = new StudentClazzStatisticsInfoDTO();
        // 统计各项指标，如：升级人数、重读人数、转班人数、退学人数、休学人数、签订合同人数、在班人数和班级总人数
        //        List<ProductDO> products = productService.findProducts(clazzId);
        //        List<StudentRecordDO> recordCountList = studentRecordMapper.statisticsCountByClazzId(clazzId);
        //        StudentRecordInfoServiceUtil.invokeStudentClazzStatisticsInfoDTO(statisticsInfoDTO, recordCountList,products);
        long totalCount = studentRecordMapper.selectCount(new LambdaQueryWrapper<StudentRecord>()
                .eq(StudentRecord::getClazzId, clazzId)
                .eq(StudentRecord::getDeletedFlag, false)
                .in(StudentRecord::getState, StudentRecordStateEnum.VALID.name()));
        statisticsInfoDTO.setTotalCount((int) totalCount);
        return statisticsInfoDTO;
    }

    @Override
    public StudentRecordRefundInfoDTO queryRefundJournalByStudentRecordId(String studentRecordId) {
        StudentRecord studentRecord = studentRecordMapper.selectById(studentRecordId);
        Assert.notNull(studentRecordId, BizExceptionProducer.produce(NemsErrorBodyEnum.DATA_EXIST, "学籍ID：" + studentRecordId));
        JournalDropout dropout = journalDropoutService.queryByStudentRecordId(studentRecordId);
        Assert.notNull(dropout, BizExceptionProducer.produce(NemsErrorBodyEnum.DATA_EXIST, "学籍ID：【" + studentRecordId + "】对应的退学凭单不存在："));
        return StudentRecordInfoServiceUtil.wrapStudentRecordRefundInfoDTO(studentRecord, dropout);
    }

}
